﻿using System;
using System.Data.Linq;
using System.Linq;
using GNUGo.Net.WebApp;
using GNUGo.Net.WebApp.Entities;
using GNUGo.Net.WebApp.WsClasses;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SuperGo.TestWebApp {
	[TestClass]
	public class GoServicesTest : BaseTest {
		readonly GoServices _goServices = new GoServices();

		[TestMethod]
		public void TestError_Warn() {
			InitializeDatabase();
			_goServices.ErrorLevel = (int)LogLevel.Warn;
			_goServices.AddGoError(52, 4, "Activity", "Message", null, DataContext, LogLevel.Warn);
			Assert.AreEqual(1, DataContext.GoErrors.Count());
			GoError goError = DataContext.GoErrors.Single();
			Assert.AreEqual("Activity", goError.Activity);
			Assert.AreEqual("Message", goError.Message);
			Assert.AreEqual((int)LogLevel.Warn, goError.ErrorLevelId);
			Assert.AreEqual(52, goError.GameId);
			Assert.AreEqual(4, goError.PlayerId);
		}

		[TestMethod]
		public void TestError_Debug() {
			InitializeDatabase();
			_goServices.ErrorLevel = (int)LogLevel.Warn;
			_goServices.AddGoError(52, 4, "Activity", "Message", null, DataContext, LogLevel.Debug);
			Assert.AreEqual(0, DataContext.GoErrors.Count());
		}

		/// <summary>
		/// Manually test that an e-mail was sent
		/// </summary>
		[TestMethod]
		public void TestError_Error() {
			InitializeDatabase();
			_goServices.ErrorLevel = (int)LogLevel.Debug;
			_goServices.AddGoError(52, 4, "Activity", "Message", null, DataContext, LogLevel.Error);
			Assert.AreEqual(1, DataContext.GoErrors.Count());
		}

		[TestMethod]
		public void TestLastMove_Start() {
			InitializeDatabase();

			const string sessionKey = "blah";
			WsPlayer lprichar = _goServices.GetCurrentPlayer(sessionKey, "lprichar");
			WsPlayer jferner = _goServices.GetCurrentPlayer(sessionKey, "jferner");

			// lprichar requests a 9x9 game with jferner with jferner as black
			WsGame newGame = new WsGame {
				GameId = 0,
				BoardSize = 9,
				Opponent = jferner,
				OpponentIsBlack = true,
				BlackHandicap = 0,
				Komi = 5.5M,
				RequestInitiatedByBlack = false
			};

			newGame = _goServices.CreateGame(newGame, lprichar, sessionKey);
			int gameId = newGame.GameId;
			string lastMove = _goServices.GetLastMove(gameId);
			Assert.IsNull(lastMove);

			_goServices.AcceptGame(gameId, jferner, sessionKey);
			lastMove = _goServices.GetLastMove(gameId);
			Assert.IsNull(lastMove);

			// jferner plays 0x0
			_goServices.AddMove(gameId, 0, 0, true, 0, sessionKey);
			lastMove = _goServices.GetLastMove(gameId);
			Assert.AreEqual(String.Format("{0} M 1 0 0", jferner.PlayerId), lastMove);
		}

		/// <summary>
		/// If the server gets restarted the LastMove cache will get destroyed.  This test ensures
		/// that that event doesn't mess up the results of GetLastMove() (the cache rebuilds itself)
		/// </summary>
		[TestMethod]
		public void TestLastMove_ServerRestart() {
			InitializeDatabase();
			_goServices.Initialize();
			
			WsPlayer jferner = _goServices.GetCurrentPlayer("blah", "jferner");

			string lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(String.Format("{0} P 24", jferner.PlayerId), lastMove);
		}
		
		[TestMethod]
		public void TestLastMove_End() {
			InitializeDatabase();
			int moveNumber = 24;

			const string sessionKey = "blah";

			WsPlayer lprichar = _goServices.GetCurrentPlayer(sessionKey, "lprichar");
			WsPlayer jferner = _goServices.GetCurrentPlayer(sessionKey, "jferner");

			// lprichar - test a move works
			const int x = 0, y = 0;
			_goServices.AddMove(52, x, y, false, 0, sessionKey);
			moveNumber++;
			string lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} M {1} {2} {3}", lprichar.PlayerId, moveNumber, x, y), lastMove);

			// jferner - test a pass works
			_goServices.AddPass(52, true, sessionKey);
			moveNumber++;
			lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} P {1}", jferner.PlayerId, moveNumber), lastMove);

			// lprichar - pass #2
			_goServices.AddPass(52, false, sessionKey);
			moveNumber++;
			lastMove = _goServices.GetLastMove(52);
			// (two passes occurred)
			Assert.AreEqual(string.Format("{0} T {1}", lprichar.PlayerId, moveNumber), lastMove);

			// lprichar - add a dead group
			_goServices.AddDeadGroup(52, 0, 0, 1, lprichar);
			lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} D {1} {2} {3}", lprichar.PlayerId, moveNumber, 0, 0), lastMove);

			// lprichar - accept dead groups
			_goServices.AcceptDeadGroups(52, lprichar, sessionKey);
			lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} A", lprichar.PlayerId), lastMove);

			// jferner - unmark dead
			_goServices.AddDeadGroup(52, 0, 0, 1, jferner);
			lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} D {1} {2} {3}", jferner.PlayerId, moveNumber, 0, 0), lastMove);

			// jferner - accept dead groups
			_goServices.AcceptDeadGroups(52, jferner, sessionKey);
			lastMove = _goServices.GetLastMove(52);
			Assert.AreEqual(string.Format("{0} A", jferner.PlayerId), lastMove);

			// lprichar - finalize
			_goServices.FinalizeGame(52, 40, 22.5M, 1, 0, lprichar, sessionKey, false);
			lastMove = _goServices.GetLastMove(52);
			Assert.IsNull(lastMove);
		}

		[TestMethod]
		public void TestTwoPasses() {
			InitializeDatabase();

			const string sessionKey = "blah";

			_goServices.AddMove(52, 0, 0, false, 0, sessionKey);
			GoGame goGame = DataContext.GoGames.Single(g => g.GameId == 52);
			Assert.IsNull(goGame.DateTwoPassesOccurred);

			_goServices.AddPass(52, true, sessionKey);
			goGame = DataContext.GoGames.Single(g => g.GameId == 52);
			Assert.IsNull(goGame.DateTwoPassesOccurred);

			_goServices.AddPass(52, false, sessionKey);
			//SetDataContext();
			DataContext.Refresh(RefreshMode.OverwriteCurrentValues, goGame);
			goGame = DataContext.GoGames.Single(g => g.GameId == 52);
			Assert.IsNotNull(goGame.DateTwoPassesOccurred);
		}
	}
}
